package com.telecom.service.impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.telecom.common.context.UserContext;
import com.telecom.common.convention.errorcode.BaseErrorCode;
import com.telecom.common.convention.exception.ClientException;
import com.telecom.common.convention.exception.ServiceException;
import com.telecom.common.convention.result.PageDTO;
import com.telecom.common.utils.JwtUtils;
import com.telecom.common.utils.RechargeNumberGenerator;
import com.telecom.mapper.RechargeRecordMapper;
import com.telecom.mapper.UserMapper;
import com.telecom.pojo.dto.admin.employee.ModifyEmployeeDTO;
import com.telecom.pojo.dto.admin.user.UserPageQueryRequestDTO;
import com.telecom.pojo.dto.admin.user.UserRechargeRequestDTO;
import com.telecom.pojo.dto.user.user.UserLoginRequestDTO;
import com.telecom.pojo.dto.user.user.UserUpdateRequestDTO;
import com.telecom.pojo.dto.user.user.UserChangePasswordRequestDTO;
import com.telecom.pojo.entity.RechargeRecord;
import com.telecom.pojo.entity.User;
import com.telecom.pojo.vo.admin.user.UserDetailVO;
import com.telecom.pojo.vo.admin.user.UserPageVO;
import com.telecom.pojo.vo.user.user.UserInfoVO;
import com.telecom.pojo.vo.user.user.UserLoginResponseVO;
import com.telecom.service.UserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 用户服务实现类
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Resource
    JwtUtils jwtUtils;
    @Resource
    UserMapper userMapper;
    @Resource
    RechargeRecordMapper rechargeRecordMapper;
    @Resource
    RechargeNumberGenerator rechargeNumberGenerator;
    
    @Override
    public UserLoginResponseVO login(UserLoginRequestDTO loginRequest) {
        log.info("用户登录，用户名：{}", loginRequest.getUsername());

        User user;
        try {
            user = userMapper.findByUsername(loginRequest.getUsername());
        } catch (Exception e) {
            throw new ClientException("用户名或密码错误", BaseErrorCode.CLIENT_ERROR);
        }
        
        // 验证用户名和密码
        String password = loginRequest.getPassword();
        password = DigestUtils.md5DigestAsHex(password.getBytes());
        if (!password.equals(user.getPassword())) {
            throw new ClientException("用户名或密码错误", BaseErrorCode.CLIENT_ERROR);
        }
        
        // 检查用户状态
        if (!user.getIsEnabled()) {
            throw new ClientException("账号已被禁用", BaseErrorCode.FORBIDDEN);
        }
        
        // 生成JWT Token
        String token = jwtUtils.generateToken(user.getId(), user.getUsername(), user.getRole());
        
        UserLoginResponseVO response = new UserLoginResponseVO();
        response.setToken(token);
        response.setUserId(user.getId());
        response.setUsername(user.getUsername());
        
        log.info("用户登录成功，用户ID：{}", user.getId());
        return response;
    }

    
    @Override
    public UserInfoVO getUserInfo(Long userId) {
        log.info("获取用户信息，用户ID：{}", userId);

        User user;
        try {
            user = userMapper.selectById(userId);
        } catch (Exception e) {
            throw new ClientException("用户不存在", BaseErrorCode.CLIENT_ERROR);
        }

        UserInfoVO userInfo = new UserInfoVO();
        BeanUtils.copyProperties(user, userInfo);
        
        return userInfo;
    }
    
    @Override
    public void updateUserInfo(UserUpdateRequestDTO updateRequest) {
        Long userId = UserContext.getUser();
        log.info("更新用户信息，用户ID：{}", userId);
        
        // 检查用户是否存在
        try {
            userMapper.selectById(userId);
        } catch (Exception e) {
            throw new ClientException("用户不存在", BaseErrorCode.CLIENT_ERROR);
        }
        
        // 构建更新的用户对象
        User user = User.builder()
                .id(userId)
                .username(updateRequest.getUsername())
                .phone(updateRequest.getPhone())
                .sex(updateRequest.getSex())
                .avatarUrl(updateRequest.getAvatarUrl())
                .updateTime(LocalDateTime.now())
                .build();
        
        try {
            userMapper.updateById(user);
        } catch (Exception e) {
            log.error("更新用户信息失败，用户ID：{}，错误信息：{}", userId, e.getMessage());
            throw new ServiceException("更新用户信息失败", BaseErrorCode.SERVICE_ERROR);
        }

        log.info("用户信息更新成功，用户ID：{}", userId);
    }

    @Override
    public void changePassword(UserChangePasswordRequestDTO changePasswordRequest) {
        Long userId = UserContext.getUser();
        log.info("用户修改密码，用户ID：{}", userId);
        
        // 检查用户是否存在
        User user;
        try {
            user = userMapper.selectById(UserContext.getUser());
        } catch (Exception e) {
            throw new ClientException("用户不存在", BaseErrorCode.CLIENT_ERROR);
        }
        
        // 验证旧密码
        String oldPasswordEncrypted = DigestUtils.md5DigestAsHex(changePasswordRequest.getOldPassword().getBytes());
        if (!oldPasswordEncrypted.equals(user.getPassword())) {
            throw new ClientException("旧密码不正确", BaseErrorCode.CLIENT_ERROR);
        }
        
        // 检查新密码是否与旧密码相同
        String newPasswordEncrypted = DigestUtils.md5DigestAsHex(changePasswordRequest.getNewPassword().getBytes());
        if (newPasswordEncrypted.equals(user.getPassword())) {
            throw new ClientException("新密码不能与旧密码相同", BaseErrorCode.CLIENT_ERROR);
        }
        
        // 更新密码
        User updateUser = User.builder()
                .id(userId)
                .password(newPasswordEncrypted)
                .updateTime(LocalDateTime.now())
                .build();
        
        try {
            userMapper.updateById(updateUser);
        } catch (Exception e) {
            log.error("修改密码失败，用户ID：{}，错误信息：{}", userId, e.getMessage());
            throw new ServiceException("修改密码失败", BaseErrorCode.SERVICE_ERROR);
        }

        log.info("用户密码修改成功，用户ID：{}", userId);
    }

    // ==================== 管理端方法实现 ====================

    @Override
    public PageDTO<UserPageVO> getUserPage(UserPageQueryRequestDTO queryRequest) {
        log.info("用户分页查询，查询参数：{}", queryRequest);

        // 使用PageHelper进行分页
        PageHelper.startPage(queryRequest.getPageNo(), queryRequest.getPageSize());

        // 查询数据（PageHelper会自动添加LIMIT子句）
        List<UserPageVO> records = userMapper.selectUserPage(queryRequest.getIdOrUsername());

        // 使用PageInfo获取分页信息
        PageInfo<UserPageVO> pageInfo = new PageInfo<>(records);

        log.info("用户分页查询成功，总数：{}，当前页数据量：{}", pageInfo.getTotal(), records.size());
        return new PageDTO<>(pageInfo.getTotal(), (long) pageInfo.getPages(), records);
    }

    @Override
    public UserDetailVO getUserDetailById(Long id) {
        log.info("根据ID查询用户详细信息，用户ID：{}", id);

        User user;
        try {
            user = userMapper.selectById(id);
        } catch (Exception e) {
            throw new ClientException("用户不存在", BaseErrorCode.CLIENT_ERROR);
        }

        UserDetailVO userDetailVO = new UserDetailVO();
        BeanUtils.copyProperties(user, userDetailVO);


        log.info("查询用户详情成功，用户名：{}", user.getUsername());
        return userDetailVO;
    }

    @Override
    public void updateUserStatus(Integer status, Long id) {
        log.info("更新用户状态，用户ID：{}，状态：{}", id, status);

        // 更新状态
        Boolean isEnabled = (status == 1);
        User user = User.builder()
                .id(id)
                .isEnabled(isEnabled)
                .updateTime(LocalDateTime.now())
                .build();

        try {
            userMapper.updateById(user);
        } catch (Exception e) {
            log.error("更新用户状态失败，用户ID：{}，错误信息：{}", id, e.getMessage());
            throw new ServiceException("更新用户状态失败", BaseErrorCode.SERVICE_ERROR);
        }

        log.info("用户状态更新成功，用户ID：{}，新状态：{}", id, isEnabled ? "启用" : "禁用");
    }

    @Override
    public void updateUser(ModifyEmployeeDTO modifyEmployeeDTO) {
        log.info("编辑用户信息，用户ID：{}", modifyEmployeeDTO.getId());

        // 检查用户是否存在
        User existingUser = null;
        try {
            existingUser = userMapper.selectById(modifyEmployeeDTO.getId());
        } catch (Exception e) {
            throw new ClientException("用户不存在", BaseErrorCode.CLIENT_ERROR);
        }

        // 构建更新的用户对象
        User user = User.builder()
                .id(modifyEmployeeDTO.getId())
                .username(modifyEmployeeDTO.getUsername())
                .phone(modifyEmployeeDTO.getPhone())
                .sex(modifyEmployeeDTO.getSex())
                .updateTime(LocalDateTime.now())
                .build();
        
        // 如果密码不为空，则加密并更新密码
        if (modifyEmployeeDTO.getPassword() != null && !modifyEmployeeDTO.getPassword().isEmpty()) {
            String encryptedPassword = DigestUtils.md5DigestAsHex(modifyEmployeeDTO.getPassword().getBytes());
            user.setPassword(encryptedPassword);
        } else {
            // 如果密码为空，则保持原密码不变
            user.setPassword(existingUser.getPassword());
        }

        try {
            userMapper.updateById(user);
        } catch (Exception e) {
            log.error("更新用户信息失败，用户ID：{}，错误信息：{}", modifyEmployeeDTO.getId(), e.getMessage());
            throw new ServiceException("更新用户信息失败", BaseErrorCode.SERVICE_ERROR);
        }

        log.info("用户信息更新成功，用户ID：{}", modifyEmployeeDTO.getId());
    }

    @Override
    @Transactional
    public void rechargeUser(UserRechargeRequestDTO rechargeRequest) {
        log.info("用户充值，用户ID：{}，充值金额：{}", rechargeRequest.getUserid(), rechargeRequest.getAmount());

        // 检查用户是否存在
        try {
            userMapper.selectById(rechargeRequest.getUserid());
        } catch (Exception e) {
            throw new ClientException("用户不存在", BaseErrorCode.CLIENT_ERROR);
        }

        // 计算新余额
        BigDecimal newBalance = rechargeRequest.getBalance().add(rechargeRequest.getAmount());

        // 更新用户余额
        User user = User.builder()
                .id(rechargeRequest.getUserid())
                .balance(newBalance)
                .updateTime(LocalDateTime.now())
                .build();

        try {
            userMapper.updateById(user);
        } catch (Exception e) {
            log.error("用户充值失败，用户ID：{}，错误信息：{}", rechargeRequest.getUserid(), e.getMessage());
            throw new ServiceException("充值失败", BaseErrorCode.SERVICE_ERROR);
        }

        // 记录充值记录
        RechargeRecord rechargeRecord = RechargeRecord.builder()
                .transactionId(rechargeNumberGenerator.generateRechargeNumber())
                .userId(rechargeRequest.getUserid())
                .amount(rechargeRequest.getAmount())
                .rechargeTime(LocalDateTime.now())
                .status(0) // 0表示SUCCESS
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build();

        try {
            rechargeRecordMapper.insert(rechargeRecord);
        } catch (Exception e) {
            log.error("保存充值记录失败，用户ID：{}，错误信息：{}", rechargeRequest.getUserid(), e.getMessage());
            // 充值记录保存失败不影响充值结果，只记录日志
        }

        log.info("用户充值成功，用户ID：{}，充值金额：{}，新余额：{}",
                 rechargeRequest.getUserid(), rechargeRequest.getAmount(), newBalance);
    }
}